package com.changge.common.core.utils;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.json.JsonReadFeature;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.databind.type.CollectionType;
import com.fasterxml.jackson.databind.type.MapType;
import com.fasterxml.jackson.datatype.guava.GuavaModule;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import com.fasterxml.jackson.module.paramnames.ParameterNamesModule;
import com.changge.common.core.exception.JacksonException;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Sets;
import org.apache.commons.lang3.BooleanUtils;

import java.io.*;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

import static com.changge.common.core.constant.DateTimeConst.*;

/**
 * Jackson工具类
 *
 * @author zhangrongkang
 * @since 2023/11/30
 */
@Slf4j
public class JacksonUtil {
	
    @Getter
    private static ObjectMapper objectMapper;

    private static final Set<JsonReadFeature> JSON_READ_FEATURES_ENABLED = Sets.newHashSet(
            // 允许在JSON中使用Java注释
            JsonReadFeature.ALLOW_JAVA_COMMENTS,
            // 允许 json 存在没用双引号括起来的 field
            JsonReadFeature.ALLOW_UNQUOTED_FIELD_NAMES,
            // 允许 json 存在使用单引号括起来的 field
            JsonReadFeature.ALLOW_SINGLE_QUOTES,
            // 允许 json 存在没用引号括起来的 ascii 控制字符
            JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS,
            // 允许 json number 类型的数存在前导 0 (例: 0001)
            JsonReadFeature.ALLOW_LEADING_ZEROS_FOR_NUMBERS,
            // 允许 json 存在 NaN, INF, -INF 作为 number 类型
            JsonReadFeature.ALLOW_NON_NUMERIC_NUMBERS,
            // 允许 只有Key没有Value的情况
            JsonReadFeature.ALLOW_MISSING_VALUES,
            // 允许数组json的结尾多逗号
            JsonReadFeature.ALLOW_TRAILING_COMMA
    );

    static {
        try {
            // 初始化
            objectMapper = initMapper();
        } catch (Exception e) {
            log.error("jackson config error", e);
        }
    }

    /**
     * 初始化ObjectMapper
     *
     * @return ObjectMapper
     */
    public static ObjectMapper initMapper() {
        JsonMapper.Builder builder = JsonMapper.builder().enable(JSON_READ_FEATURES_ENABLED.toArray(new JsonReadFeature[0]));
        return initMapperConfig(builder.build());
    }

    public static ObjectMapper newObjectMapper() {
    	return initMapper();
    }

    /**
     * 初始化ObjectMapper配置
     *
     * @param objectMapper objectMapper对象
     * @return 配置后ObjectMapper
     */
    public static ObjectMapper initMapperConfig(ObjectMapper objectMapper) {
        objectMapper.setDateFormat(new SimpleDateFormat(DATE_TIME_FORMAT));
        // 长整型转字符串
        SimpleModule simpleModule = new SimpleModule();
		// 长整型数字转字符串
		simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
		simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
		simpleModule.addSerializer(BigInteger.class, ToStringSerializer.instance);
		simpleModule.addSerializer(BigDecimal.class, ToStringSerializer.instance);
		objectMapper.registerModule(simpleModule);
        // 配置序列化级别
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        // 配置JSON缩进支持
        objectMapper.configure(SerializationFeature.INDENT_OUTPUT, false);
        // 允许单个数值当做数组处理
        objectMapper.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
        // 禁止重复键, 抛出异常
        objectMapper.enable(DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY);
        //  禁止使用int代表Enum的order()來反序列化Enum
        objectMapper.enable(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS);
        // 有属性不能映射的时候不报错
        objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        // 对象为空时不抛异常
        objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
        // 时间格式
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        // 允许未知字段
        objectMapper.enable(JsonGenerator.Feature.IGNORE_UNKNOWN);
        // 序列化BigDecimal时之间输出原始数字还是科学计数, 默认false, 即是否以toPlainString()科学计数方式来输出
        objectMapper.enable(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN);
        // 识别Java8时间
        objectMapper.registerModule(new ParameterNamesModule());
        objectMapper.registerModule(new Jdk8Module());
        JavaTimeModule javaTimeModule = new JavaTimeModule();
        javaTimeModule
                // 序列化：Java对象转Json
                .addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DATE_TIME_FORMAT)))
                .addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DATE_FORMAT)))
                .addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(TIME_FORMAT)))
                // 反序列化：Json转Java对象
                .addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DATE_TIME_FORMAT)))
                .addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DATE_FORMAT)))
                .addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(TIME_FORMAT)));
        objectMapper.registerModule(javaTimeModule);
        // 识别Guava包的类
        objectMapper.registerModule(new GuavaModule());
        objectMapper.findAndRegisterModules();
        return objectMapper;
    }

    /**
     * JSON反序列化
     */
    public static <T> T from(URL url, Class<T> type) {
        try {
            return objectMapper.readValue(url, type);
        } catch (IOException e) {
            throw new JacksonException(StringUtil.messageFormat("jackson from error, url: {}, type: {}", url.getPath(), type), e);
        }
    }

    /**
     * JSON反序列化
     */
    public static <T> T from(URL url, TypeReference<T> type) {
        try {
            return objectMapper.readValue(url, type);
        } catch (IOException e) {
            throw new JacksonException(StringUtil.messageFormat("jackson from error, url: {}, type: {}", url.getPath(), type), e);
        }
    }

    /**
     * JSON集合反序列化
     */
    public static <T> List<T> fromList(URL url, Class<T> type) {
        try {
            CollectionType collectionType = objectMapper.getTypeFactory().constructCollectionType(ArrayList.class, type);
            return objectMapper.readValue(url, collectionType);
        } catch (IOException e) {
            throw new JacksonException(StringUtil.messageFormat("jackson from error, url: {}, type: {}", url.getPath(), type), e);
        }
    }

    /**
     * JSON反序列化
     */
    public static <T> T from(InputStream inputStream, Class<T> type) {
        try {
            return objectMapper.readValue(inputStream, type);
        } catch (IOException e) {
            throw new JacksonException(StringUtil.messageFormat("jackson from error, type: {}", type), e);
        }
    }

    /**
     * JSON反序列化
     */
    public static <T> T from(InputStream inputStream, TypeReference<T> type) {
        try {
            return objectMapper.readValue(inputStream, type);
        } catch (IOException e) {
            throw new JacksonException(StringUtil.messageFormat("jackson from error, type: {}", type), e);
        }
    }

    /**
     * JSON反序列化（List）
     */
    public static <T> List<T> fromList(InputStream inputStream, Class<T> type) {
        try {
            CollectionType collectionType = objectMapper.getTypeFactory().constructCollectionType(ArrayList.class, type);
            return objectMapper.readValue(inputStream, collectionType);
        } catch (IOException e) {
            throw new JacksonException(StringUtil.messageFormat("jackson from error, type: {}", type), e);
        }
    }

    /**
     * JSON反序列化
     */
    public static <T> T from(File file, Class<T> type) {
        try {
            return objectMapper.readValue(file, type);
        } catch (IOException e) {
            throw new JacksonException(StringUtil.messageFormat("jackson from error, file path: {}, type: {}", file.getPath(), type), e);
        }
    }

    /**
     * JSON反序列化
     */
    public static <T> T from(File file, TypeReference<T> type) {
        try {
            return objectMapper.readValue(file, type);
        } catch (IOException e) {
            throw new JacksonException(StringUtil.messageFormat("jackson from error, file path: {}, type: {}", file.getPath(), type), e);
        }
    }

    /**
     * JSON反序列化（List）
     */
    public static <T> List<T> fromList(File file, Class<T> type) {
        try {
            CollectionType collectionType = objectMapper.getTypeFactory().constructCollectionType(ArrayList.class, type);
            return objectMapper.readValue(file, collectionType);
        } catch (IOException e) {
            throw new JacksonException(StringUtil.messageFormat("jackson from error, file path: {}, type: {}", file.getPath(), type), e);
        }
    }

    /**
     * JSON反序列化
     */
    public static <T> T from(String json, Class<T> type) {
        return from(json, (Type) type);
    }

    /**
     * JSON反序列化
     */
    public static <T> T from(String json, TypeReference<T> type) {
        return from(json, type.getType());
    }

    /**
     * JSON反序列化
     */
    public static <T> T from(String json, Type type) {
        if (StringUtil.isEmpty(json)) {
            return null;
        }
        try {
            JavaType javaType = objectMapper.getTypeFactory().constructType(type);
            return objectMapper.readValue(json, javaType);
        } catch (IOException e) {
            throw new JacksonException(StringUtil.messageFormat("jackson from error, json: {}, type: {}", json, type), e);
        }
    }

    /**
     * JSON反序列化（List）
     */
    public static <T> List<T> fromList(String json, Class<T> type) {
        if (StringUtil.isEmpty(json)) {
            return null;
        }
        try {
            CollectionType collectionType = objectMapper.getTypeFactory().constructCollectionType(ArrayList.class, type);
            return objectMapper.readValue(json, collectionType);
        } catch (IOException e) {
            throw new JacksonException(StringUtil.messageFormat("jackson from error, json: {}, type: {}", json, type), e);
        }
    }

    public static <T> Set<T> fromSet(String json, Class<T> type) {
        if (StringUtil.isEmpty(json)) {
            return null;
        }
        try {
            CollectionType collectionType = objectMapper.getTypeFactory().constructCollectionType(HashSet.class, type);
            return objectMapper.readValue(json, collectionType);
        } catch (IOException e) {
            throw new JacksonException(StringUtil.messageFormat("jackson from error, json: {}, type: {}", json, type), e);
        }
    }

    /**
     * JSON反序列化（Map）
     */
    public static Map<String, Object> fromMap(String json) {
        if (StringUtil.isEmpty(json)) {
            return null;
        }
        try {
            MapType mapType = objectMapper.getTypeFactory().constructMapType(HashMap.class, String.class, Object.class);
            return objectMapper.readValue(json, mapType);
        } catch (IOException e) {
            throw new JacksonException(StringUtil.messageFormat("jackson from error, json: {}, type: {}", json), e);
        }
    }

    public static <T> Map<String, T> fromMap(String json, Class<T> clazz) {
        if (StringUtil.isEmpty(json)) {
            return null;
        }
        try {
            MapType mapType = objectMapper.getTypeFactory().constructMapType(HashMap.class, String.class, clazz);
            return objectMapper.readValue(json, mapType);
        } catch (IOException e) {
            throw new JacksonException(StringUtil.messageFormat("jackson from error, json: {}, type: {}", json), e);
        }
    }

    /**
     * 序列化为JSON
     */
    public static <T> String to(List<T> list) {
        try {
            return objectMapper.writeValueAsString(list);
        } catch (JsonProcessingException e) {
            throw new JacksonException(StringUtil.messageFormat("jackson to error, data: {}", list), e);
        }
    }

    /**
     * 序列化为JSON
     */
    public static <T> String toJson(T t) {
        try {
            return objectMapper.writeValueAsString(t);
        } catch (JsonProcessingException e) {
            throw new JacksonException(StringUtil.messageFormat("jackson to error, data: {}", t), e);
        }
    }

    /**
     * 序列化文件集合为JSON
     *
     * @param path 文件路径
     * @param list 集合
     * @param <T> 集合元素类型
     */
    public static <T> void toFile(String path, List<T> list) {
        try (Writer writer = new FileWriter(new File(path), true)) {
            objectMapper.writer().writeValues(writer).writeAll(list);
        } catch (Exception e) {
            throw new JacksonException(StringUtil.messageFormat("jackson to file error, path: {}, list: {}", path, list), e);
        }
    }

    /**
     * 序列化File为JSON
     */
    public static <T> void toFile(String path, T t) {
        try (Writer writer = new FileWriter(path, true)) {
            objectMapper.writer().writeValues(writer).write(t);
        } catch (Exception e) {
            throw new JacksonException(StringUtil.messageFormat("jackson to file error, path: {}, data: {}", path, t), e);
        }
    }

    /**
     * 从Json串中获取某个字段
     *
     * @return String，默认为 null
     */
    public static String getAsString(String json, String key) {
        if (StringUtil.isEmpty(json)) {
            return null;
        }
        try {
            JsonNode jsonNode = getAsJsonObject(json, key);
            if (null == jsonNode) {
                return null;
            }
            return getAsString(jsonNode);
        } catch (Exception e) {
            throw new JacksonException(StringUtil.messageFormat("jackson get string error, json: {}, key: {}", json, key), e);
        }
    }

    private static String getAsString(JsonNode jsonNode) {
        return jsonNode.isTextual() ? jsonNode.textValue() : jsonNode.toString();
    }

    /**
     * 从json串中获取某个字段
     * @return int，默认为 0
     */
    public static int getAsInt(String json, String key) {
        if (StringUtil.isEmpty(json)) {
            return 0;
        }
        try {
            JsonNode jsonNode = getAsJsonObject(json, key);
            if (null == jsonNode) {
                return 0;
            }
            return jsonNode.isInt() ? jsonNode.intValue() : Integer.parseInt(getAsString(jsonNode));
        } catch (Exception e) {
            throw new JacksonException(StringUtil.messageFormat("jackson get int error, json: {}, key: {}", json, key), e);
        }
    }

    /**
     * 从json串中获取某个字段
     * @return long，默认为 0
     */
    public static long getAsLong(String json, String key) {
        if (StringUtil.isEmpty(json)) {
            return 0L;
        }
        try {
            JsonNode jsonNode = getAsJsonObject(json, key);
            if (null == jsonNode) {
                return 0L;
            }
            return jsonNode.isLong() ? jsonNode.longValue() : Long.parseLong(getAsString(jsonNode));
        } catch (Exception e) {
            throw new JacksonException(StringUtil.messageFormat("jackson get long error, json: {}, key: {}", json, key), e);
        }
    }

    /**
     * 从json串中获取某个字段
     * @return double，默认为 0.0
     */
    public static double getAsDouble(String json, String key) {
        if (StringUtil.isEmpty(json)) {
            return 0.0;
        }
        try {
            JsonNode jsonNode = getAsJsonObject(json, key);
            if (null == jsonNode) {
                return 0.0;
            }
            return jsonNode.isDouble() ? jsonNode.doubleValue() : Double.parseDouble(getAsString(jsonNode));
        } catch (Exception e) {
            throw new JacksonException(StringUtil.messageFormat("jackson get double error, json: {}, key: {}", json, key), e);
        }
    }

    /**
     * 从json串中获取某个字段
     * @return BigInteger，默认为 0.0
     */
    public static BigInteger getAsBigInteger(String json, String key) {
        if (StringUtil.isEmpty(json)) {
            return new BigInteger(String.valueOf(0.00));
        }
        try {
            JsonNode jsonNode = getAsJsonObject(json, key);
            if (null == jsonNode) {
                return new BigInteger(String.valueOf(0.00));
            }
            return jsonNode.isBigInteger() ? jsonNode.bigIntegerValue() : new BigInteger(getAsString(jsonNode));
        } catch (Exception e) {
            throw new JacksonException(StringUtil.messageFormat("jackson get big integer error, json: {}, key: {}", json, key), e);
        }
    }

    /**
     * 从json串中获取某个字段
     * @return BigDecimal，默认为 0.00
     */
    public static BigDecimal getAsBigDecimal(String json, String key) {
        if (StringUtil.isEmpty(json)) {
            return new BigDecimal("0.00");
        }
        try {
            JsonNode jsonNode = getAsJsonObject(json, key);
            if (null == jsonNode) {
                return new BigDecimal("0.00");
            }
            return jsonNode.isBigDecimal() ? jsonNode.decimalValue() : new BigDecimal(getAsString(jsonNode));
        } catch (Exception e) {
            throw new JacksonException(StringUtil.messageFormat("jackson get big decimal error, json: {}, key: {}", json, key), e);
        }
    }

    /**
     * 从json串中获取某个字段
     * @return boolean, 默认为false
     */
    public static boolean getAsBoolean(String json, String key) {
        if (StringUtil.isEmpty(json)) {
            return false;
        }
        try {
            JsonNode jsonNode = getAsJsonObject(json, key);
            if (null == jsonNode) {
                return false;
            }
            if (jsonNode.isBoolean()) {
                return jsonNode.booleanValue();
            } else {
                if (jsonNode.isTextual()) {
                    String textValue = jsonNode.textValue();
                    if ("1".equals(textValue)) {
                        return true;
                    } else {
                        return BooleanUtils.toBoolean(textValue);
                    }
                } else {// number
                    return BooleanUtils.toBoolean(jsonNode.intValue());
                }
            }
        } catch (Exception e) {
            throw new JacksonException(StringUtil.messageFormat("jackson get boolean error, json: {}, key: {}", json, key), e);
        }
    }

    /**
     * 从json串中获取某个字段
     * @return byte[], 默认为 null
     */
    public static byte[] getAsBytes(String json, String key) {
        if (StringUtil.isEmpty(json)) {
            return null;
        }
        try {
            JsonNode jsonNode = getAsJsonObject(json, key);
            if (null == jsonNode) {
                return null;
            }
            return jsonNode.isBinary() ? jsonNode.binaryValue() : getAsString(jsonNode).getBytes();
        } catch (Exception e) {
            throw new JacksonException(StringUtil.messageFormat("jackson get byte error, json: {}, key: {}", json, key), e);
        }
    }

    /**
     * 从json串中获取某个字段
     * @return object, 默认为 null
     */
    public static <T> T getAsObject(String json, String key, Class<T> type) {
        if (StringUtil.isEmpty(json)) {
            return null;
        }
        try {
            JsonNode jsonNode = getAsJsonObject(json, key);
            if (null == jsonNode) {
                return null;
            }
            JavaType javaType = objectMapper.getTypeFactory().constructType(type);
            return from(getAsString(jsonNode), javaType);
        } catch (Exception e) {
            throw new JacksonException(StringUtil.messageFormat("jackson get list error, json: {}, key: {}, type: {2}", json, key, type), e);
        }
    }


    /**
     * 从json串中获取某个字段
     * @return list, 默认为 null
     */
    public static <T> List<T> getAsList(String json, String key, Class<T> type) {
        if (StringUtil.isEmpty(json)) {
            return null;
        }
        try {
            JsonNode jsonNode = getAsJsonObject(json, key);
            if (null == jsonNode) {
                return null;
            }
            CollectionType collectionType = objectMapper.getTypeFactory().constructCollectionType(ArrayList.class, type);
            return from(getAsString(jsonNode), collectionType);
        } catch (Exception e) {
            throw new JacksonException(StringUtil.messageFormat("jackson get list error, json: {}, key: {}, type: {2}", json, key, type), e);
        }
    }

    /**
     * 从json串中获取某个字段
     * @return JsonNode, 默认为 null
     */
    public static JsonNode getAsJsonObject(String json, String key) {
        try {
            JsonNode node = objectMapper.readTree(json);
            if (null == node) {
                return null;
            }
            return node.get(key);
        } catch (IOException e) {
            throw new JacksonException(StringUtil.messageFormat("jackson get object from json error, json: {}, key: {}", json, key), e);
        }
    }

    /**
     * 向json中添加属性
     * @return json
     */
    public static <T> String add(String json, String key, T value) {
        try {
            JsonNode node = objectMapper.readTree(json);
            add(node, key, value);
            return node.toString();
        } catch (IOException e) {
            throw new JacksonException(StringUtil.messageFormat("jackson add error, json: {}, key: {}, value: {2}", json, key, value), e);
        }
    }

    /**
     * 向json中添加属性
     */
    private static <T> void add(JsonNode jsonNode, String key, T value) {
        if (value instanceof String) {
            ((ObjectNode) jsonNode).put(key, value.toString());
        } else if (value instanceof Short) {
            ((ObjectNode) jsonNode).put(key, (Short) value);
        } else if (value instanceof Integer) {
            ((ObjectNode) jsonNode).put(key, (Integer) value);
        } else if (value instanceof Long) {
            ((ObjectNode) jsonNode).put(key, (Long) value);
        } else if (value instanceof Float) {
            ((ObjectNode) jsonNode).put(key, (Float) value);
        } else if (value instanceof Double) {
            ((ObjectNode) jsonNode).put(key, (Double) value);
        } else if (value instanceof BigDecimal) {
            ((ObjectNode) jsonNode).put(key, (BigDecimal) value);
        } else if (value instanceof BigInteger) {
            ((ObjectNode) jsonNode).put(key, (BigInteger) value);
        } else if (value instanceof Boolean) {
            ((ObjectNode) jsonNode).put(key, (Boolean) value);
        } else if (value instanceof byte[]) {
            ((ObjectNode) jsonNode).put(key, (byte[]) value);
        } else {
            ((ObjectNode) jsonNode).put(key, toJson(value));
        }
    }

    /**
     * 除去json中的某个属性
     *
     * @return 更新后json
     */
    public static String remove(String json, String key) {
        try {
            JsonNode node = objectMapper.readTree(json);
            ((ObjectNode) node).remove(key);
            return node.toString();
        } catch (IOException e) {
            throw new JacksonException(StringUtil.messageFormat(StringUtil.messageFormat("jackson remove error, json: {}, key: {}", json, key)), e);
        }
    }

    /**
     * 更新json中的属性
     *
     * @param json JSON串
     * @param key Key
     * @param value 更新Value
     * @param <T> Value类型
     * @return 更新后JSON串
     */
    public static <T> String update(String json, String key, T value) {
        try {
            JsonNode node = objectMapper.readTree(json);
            ((ObjectNode) node).remove(key);
            add(node, key, value);
            return node.toString();
        } catch (IOException e) {
            throw new JacksonException(StringUtil.messageFormat(StringUtil.messageFormat("jackson update error, json: {}, key: {}, value: {2}", json, key, value)), e);
        }
    }

    /**
     * 格式化Json
     *
     * @param json json串
     * @return 格式化json
     */
    public static String format(String json) {
        try {
            JsonNode node = objectMapper.readTree(json);
            return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(node);
        } catch (IOException e) {
            throw new JacksonException(StringUtil.messageFormat(StringUtil.messageFormat("jackson format json error, json: {}", json)), e);
        }
    }

    /**
     * 判断字符串是否是json
     *
     * @param json 字符串
     * @return true--是，false--不是
     */
    public static boolean isJson(String json) {
        try {
            objectMapper.readTree(json);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

}